﻿using Microsoft.Extensions.Logging;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using System.Xml;

namespace ConsoleApp1.Model
{
    public class BookToXmlTool
    {
        public ILogger<BookToXmlTool> Logger { get; set; }
        public BookToXmlTool(ILogger<BookToXmlTool> logger)
        {
            this.Logger = logger;
        }

        public void Start(TestMode testMode)
        {
            //先创建个xml文件对象
            XmlDocument doc = new XmlDocument();
            //这个是xml文件第一行的说明信息
            XmlDeclaration xmlDeclaration = doc.CreateXmlDeclaration("1.0", "utf-8", null);
            doc.AppendChild(xmlDeclaration);
            BookXmlAttrbute? data = testMode.GetType().GetCustomAttributes(typeof(BookXmlAttrbute)).FirstOrDefault() as BookXmlAttrbute;
            string rootKey = "";
            if (data != null)
                rootKey = data.bookPropertyName;
            else
                rootKey = testMode.GetType().Name;
            XmlElement root = doc.CreateElement(rootKey);
            doc.AppendChild(root);
            Run(testMode.GetType(), testMode, doc, root);

            //文档一些设置
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Encoding = System.Text.Encoding.UTF8;
            settings.Indent = true;
            settings.IndentChars = "    ";
            //如果自己未指定路径,xml文件默认创建在bin目录下的debug目录里
            XmlWriter writer = XmlWriter.Create("data2.xml", settings);
            doc.Save(writer);
        }
        public void Run(Type type, object? testMode, XmlDocument xmlDocument, XmlElement xmlElementParent)
        {
            PropertyInfo[] propers = type.GetProperties(BindingFlags.Instance | BindingFlags.Public).ToArray();
            foreach (PropertyInfo prop in propers)
            {
                BookXmlAttrbute? propertyInfo = prop.GetCustomAttributes(typeof(BookXmlAttrbute)).FirstOrDefault() as BookXmlAttrbute;
                string xmlKey = "";
                //var w = prop.PropertyType.Name == "List`1";
                if (propertyInfo != null)
                    xmlKey = propertyInfo.bookPropertyName;
                else
                    xmlKey = prop.Name;
                if (prop.PropertyType.IsGenericType && prop.PropertyType.GetInterface("IEnumerable`1") != null)
                {
                    if (prop.PropertyType.GetGenericArguments()[0].IsClass && !prop.PropertyType.GetGenericArguments()[0].IsPrimitive && prop.PropertyType.GetGenericArguments()[0] != typeof(string) && prop.PropertyType.GetGenericArguments()[0] != typeof(string[]))
                    {
                        if (prop.GetValue(testMode) != null)
                        {

                            IEnumerable<object> value = (IEnumerable<object>)prop.GetValue(testMode);
                            if (value.Count() > 0)
                            {
                                XmlElement book = xmlDocument.CreateElement(xmlKey);
                                xmlElementParent.AppendChild(book);
                                foreach (object item in value)
                                {
                                    string GenericName = prop.PropertyType.GetGenericArguments()[0].Name;
                                    var parent = xmlDocument.CreateElement(GenericName);
                                    book.AppendChild(parent);
                                    Run(item.GetType(), item, xmlDocument, parent);
                                }
                            }
                        }
                    }
                }
                else if (prop.PropertyType.IsClass && !prop.PropertyType.IsPrimitive && prop.PropertyType != typeof(string) && prop.PropertyType != typeof(string[]))
                {

                    var value = prop.GetValue(testMode);
                    if (value != null)
                    {
                        XmlElement book = xmlDocument.CreateElement(xmlKey);
                        xmlElementParent.AppendChild(book);
                        Run(value.GetType(), value, xmlDocument, book);
                    }
                }
                else
                {
                    var value = prop.GetValue(testMode);
                    XmlElement book = xmlDocument.CreateElement(xmlKey);
                    //给book元素设置属性,用于描述book
                    //XmlAttribute attr = xmlDocument.CreateAttribute("Value");
                    //attr.Value = "历史文学";
                    //book.Attributes.Append(attr);
                    book.InnerText = value?.ToString();
                    xmlElementParent.AppendChild(book);
                }
            }
        }
    }
}
